﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ZYSocket.Server;
using System.Net.Sockets;
using CSM.Lib;
using CSM.Lib.Protocol;
using CSM.BLL.UserManager;

namespace CSM.Server
{
	class Program
	{
		static ZYSocketSuper server = new ZYSocketSuper();

		static void Main(string[] args)
		{
			server.BinaryInput = new BinaryInputHandler(BinaryInputHandler);
			server.Connetions = new ConnectionFilter(ConnectionFilter);
			server.MessageInput = new MessageInputHandler(MessageInputHandler);
			server.MessageOut += new EventHandler<LogOutEventArgs>(server_MessageOut);
			server.Start();

			Console.ReadLine();
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		static void server_MessageOut(object sender, LogOutEventArgs e)
		{
			//输出消息
			Console.WriteLine(e.MessClass.ToString() + ": " + e.Mess);
		}

		/// <summary>
		/// 用户连接的代理
		/// </summary>
		/// <param name="socketAsync">连接的SOCKET</param>
		/// <returns>如果返回FALSE 则断开连接,这里注意下 可以用来封IP</returns>
		static bool ConnectionFilter(SocketAsyncEventArgs socketAsync)
		{
			Console.WriteLine("UserConn {0}", socketAsync.AcceptSocket.RemoteEndPoint.ToString());

			return true;
		}

		/// <summary>
		/// 用户断开代理（你可以根据socketAsync 读取到断开的
		/// </summary>
		/// <param name="message">断开消息</param>
		/// <param name="socketAsync">断开的SOCKET</param>
		/// <param name="erorr">错误的ID</param>
		static void MessageInputHandler(string message, SocketAsyncEventArgs socketAsync, int erorr)
		{
			if (socketAsync.UserToken != null)
			{
				UserInfo user = ((UserBuffer)socketAsync.UserToken).Tag as UserInfo;

				Console.WriteLine(user.NickName + " 退了");

				socketAsync.UserToken = null; //这里一定要设置为NULL 否则出现的错误 很爽
			}
		}

		/// <summary>
		/// 数据包输入
		/// </summary>
		/// <param name="data">输入数据</param>
		/// <param name="socketAsync">该数据包的通讯SOCKET</param>
		static void BinaryInputHandler(byte[] data, SocketAsyncEventArgs socketAsync)
		{
			try
			{
				#region 初始化UserToken，UserToken为nul表示新用户登入，同时等待后面为UserInfo初始化
				if (socketAsync.UserToken == null)
				{
					socketAsync.UserToken = new UserBuffer();
				}
				UserBuffer buffer = (UserBuffer)socketAsync.UserToken;
				#endregion

				#region 解析data，同时输出p
				ProtocolBase[] p = null;
				try
				{
					p = Protocol.Decoder(data, buffer.BuffManger);
				}
				catch(Exception)
				{
					if (buffer.Tag != null)
					{
						//Console.WriteLine(((UserInfo)buffer.Tag).NickName + ": " + ex.Message + "\n" + ex.StackTrace);
					}
					else
					{
						//
					}
				}
				#endregion

				#region 处理每一个p
				if (p != null)
				{
					foreach (ProtocolReqBase item in p)
					{
 						#region 如果是新用户登陆,第一个包必须是UserLoginReq
						if (buffer.Tag == null)
						{
							if (item is UserLoginReq)
							{
								buffer.Tag = UserManager.Login(item as UserLoginReq);
							}
							else
							{
								throw new Exception("接收到非法的协议报");
							}
						}
						#endregion

						ProtocolBase resp = item.Response((UserInfo)buffer.Tag);
						server.SendData(socketAsync.AcceptSocket, Protocol.Encoder(resp));
					}
				}
				#endregion
			}
			catch (Exception ex)
			{
				Console.WriteLine(ex.Message + "\n" + ex.StackTrace);
			}
			
		}
	}
}
